package com.mck.service.impl;

import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.google.common.collect.Lists;
import com.mck.anno.OperationLog;
import com.mck.entity.*;
import com.mck.service.OperationLogService;
import com.mck.service.UserClassnameService;
import com.mck.utils.IpLocationUtil;
import com.mck.utils.JwtUtil;
import com.mck.mapper.UserClassnameMapper;
import com.mck.mapper.UserMapper;
import com.mck.service.UserService;
import jakarta.servlet.http.HttpServletRequest;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Slf4j
@Service
@RequiredArgsConstructor  // 自动生成包含所有 final 字段的构造器
public class UserServiceImpl implements UserService {
    // @Autowired
    private final UserMapper userMapper;
    @Autowired
    private UserClassnameMapper userClassnameMapper;
    @Autowired
    private UserClassnameService UserClassnameService;
    @Autowired
    private OperationLogService operationLogService;
    @Autowired
    private PasswordEncoder passwordEncoder;

    private void prepareUser(User user) {
        user.setCreateTime(LocalDateTime.now());
        user.setPassword(passwordEncoder.encode(user.getPassword()));
    }

    // 登录
    @Override
    public LoginInfo login(User user) {
        User userInfo = new User();
        userInfo.setAccount(user.getAccount());

        List<User> userList = userMapper.findUserInfoByUserInfo(userInfo);
        if (!userList.isEmpty()) {
            User u = userList.getFirst();

            // 验证密码是否正确
            boolean isTrue = passwordEncoder.matches(user.getPassword(), u.getPassword());

            if (!isTrue) {
                return null;
            }

            // 生成jwt
            Map<String, Object> claims = new HashMap<>();
            claims.put("userId", u.getUserId());
            claims.put("userTypeId", u.getUserTypeId());
            // claims.put("uname", u.getUname());
            String token = JwtUtil.generateToken(claims);

            // 存入记录
            // 获取请求对象
            HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes()).getRequest();

            // 获取ip地址
            String ip = IpLocationUtil.getIp(request);
            String address = IpLocationUtil.getAddress(ip);

            OperLog operationLog = new OperLog();
            operationLog.setUserId(u.getUserId());
            operationLog.setMethod("POST");
            operationLog.setUrl("/user/login");
            operationLog.setCreateTime(LocalDateTime.now());
            operationLog.setIp(ip);
            operationLog.setAddress(address);

            operationLogService.saveOperationLog(operationLog);

            // 获取班级id
            List<Classname> classnameList = UserClassnameService.getClassnameListByUserId(u.getUserId());
            List<Integer> classIdList = new ArrayList<>();
            for (Classname classname : classnameList) {
                classIdList.add(classname.getClassId());
            }

            // 返回用户信息
            return new LoginInfo(u.getUserId(), u.getUserTypeId(), u.getAvatarId(), classIdList, u.getUname(), u.getEnable());
        }

        return null;
    }

    // 查询所有用户
    @Override
    @Cacheable(value = "userList", key = "'page_'+#currentPage+'_size_'+#pageSize")
    public Pagination<User> findAllUser(Integer currentPage, Integer pageSize) {
        try (Page<?> page = PageHelper.startPage(currentPage, pageSize)) {
            List<User> userList = userMapper.findAllUser();
            return new Pagination<>(page, userList);
        }
    }

    // 根据条件查询用户
    @Override
    @Cacheable(value = "userList", key = "#user", unless = "#result.isEmpty()")
    public List<User> findUserInfoByUserInfo(User user) {
        return userMapper.findUserInfoByUserInfo(user);
    }

    // 根据id删除用户
    @OperationLog
    @Override
    @CacheEvict(value = "userList", key = "'all'")
    public void deleteUserById(Integer userId) {
        // User user = new User();
        // user.setUserId(userId);
        // List<User> userInfo = userMapper.findUserInfoByUserInfo(user);
        // FileInfo fileInfo = new FileInfo();
        // fileInfo.setUserId(userId);
        // fileMapper.deleteFile(fileInfo);

        userMapper.deleteUserById(userId);
    }

    // 删除用户列表
    @OperationLog
    @Override
    @CacheEvict(value = "userList", key = "'all'")
    public void deleteUserList(List<User> userList) {
        for (User user : userList) {
            userMapper.deleteUserList(user);
        }
    }

    // 添加用户
    @OperationLog
    @Override
    @Transactional
    public void addUser(User user) {
        prepareUser(user);

        // 添加用户
        userMapper.addUser(user);

        // 班级关联
        if (user.getClassId() != null) {
            List<UserClassname> userClassname = user.getClassId().stream().map(classId -> new UserClassname(user.getUserId(), classId, user.getUserTypeId())).collect(Collectors.toList());
            userClassnameMapper.addUserClassname(userClassname);
        }
    }

    // 添加用户列表
    @OperationLog
    @Override
    @Transactional(rollbackFor = Exception.class)
    @CacheEvict(value = "userList", key = "'all'")
    public void addUserList(List<User> userList) {
        // for (User user : userList) {
        //     user.setCreateTime(LocalDateTime.now());
        //
        //     // 密码加密
        //     String encryptPassword = passwordEncoder.encode(user.getPassword());
        //     user.setPassword(encryptPassword);
        //
        //
        //     userMapper.addUserList(user);
        //
        //     // 关联班级
        //     List<User> userInfo = userMapper.findUserInfoByUserInfo(user);  // 获取对应用户数据
        //     Integer userId = userInfo.getFirst().getUserId();
        //     Integer userTypeId = userInfo.getFirst().getUserTypeId();
        //     List<Integer> classId = user.getClassId();
        //     for (Integer ClassId : classId) {
        //         userClassnameMapper.addUserClassname(userId, ClassId, userTypeId);
        //     }
        // }

        userList.forEach(this::prepareUser); // 预处理所有用户
        List<List<User>> batches = Lists.partition(userList, 10); // 使用 Guava 分片
        batches.forEach(batch -> {
            userMapper.insertUserList(batch); // 插入当前批次用户

            // 检查当前批次用户的userId是否生成
            batch.forEach(user -> {
                // log.debug("插入用户: account={}, userId={}", user.getAccount(), user.getUserId());

                if (user.getUserId() == null) {
                    throw new IllegalStateException("用户ID未生成: " + user.getAccount());
                }
            });

            // 仅处理当前批次的用户来构建关联数据
            List<UserClassname> userClassname = batch.stream().flatMap(user -> user.getClassId().stream().map(classId -> {
                if (classId == null || user.getUserTypeId() == null) {
                    throw new IllegalArgumentException("参数错误: classId或userTypeId为空");
                }
                return UserClassname.builder().userId(user.getUserId()).classId(classId).userTypeId(user.getUserTypeId()).build();
            })).collect(Collectors.toList());

            // userClassname.forEach(uc -> log.debug("正确关联数据: userId={}, classId={}, userTypeId={}", uc.getUserId(), uc.getClassId(), uc.getUserTypeId()));

            userClassnameMapper.addUserClassname(userClassname); // 插入关联表
        });
    }

    // 修改用户信息
    @OperationLog
    @Override
    @CacheEvict(value = "userList", key = "'all'")
    public void updateUser(User user) {
        if (user.getPassword() != null) {
            prepareUser(user);
        }

        if (user.getClassId() != null) {
            // 移除原有数据
            userClassnameMapper.deleteUserClassnameByUserId(user.getUserId());

            // 添加数据
            userClassnameMapper.addUserClassname(user.getClassId()
                    .stream().map(classId -> new UserClassname
                            (user.getUserId(), classId, user.getUserTypeId()))
                    .collect(Collectors.toList()));
        }

        userMapper.updateUser(user);
    }
}
